﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace ZackFlame.IronBrainFuck
{
    /// <summary>
    /// Абстрактный исполнитель BrainFuck программ.
    /// </summary>
    public abstract class BrainFuckMachine
    {
        /// <summary>
        /// Максимальное значение индекса текущей ячейки,
        /// после прохода через которое он обнуляется.
        /// </summary>
        public static readonly int MaxCellIndex = 65535;
        /// <summary>
        /// Максимальное значение текущей ячейки, после
        /// прохода через которое она обнуляется.
        /// </summary>
        public static readonly int MaxCellValue = 65535;

        /// <summary>
        /// "Лента" ячеек для программ.
        /// </summary>
        public UInt16[] Cells { get; set; }
        /// <summary>
        /// Индекс текущей ячейки "ленты".
        /// </summary>
        public UInt16 CellIndex { get; set; }
        /// <summary>
        /// Поток для ввода (операции "," и "@").
        /// </summary>
        public TextReader Input { get; set; }
        /// <summary>
        /// Поток для вывода (операции "." и "#").
        /// </summary>
        public TextWriter Output { get; set; }

        /// <summary>
        /// Инициализирует новую BrainFuck машину.
        /// </summary>
        public BrainFuckMachine()
        {
            Cells = new UInt16[UInt16.MaxValue + 1];
            CellIndex = 0;
        }

        /// <summary>
        /// Устанавливает для машины начальное состояние.
        /// </summary>
        public void Reset()
        {
            CellIndex = 0;
            Array.Clear(Cells, 0, Cells.Length);
        }

        /// <summary>
        /// Исполняет BrainFuck программу на данной машине.
        /// </summary>
        /// <param name="brainFuckProgram">Код программы для исполнения.</param>
        public abstract void Execute(string brainFuckProgram);
    }
}
